package com.ozo.easy.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ozo.easy.common.exception.ServiceException;
import com.ozo.easy.common.model.BaseBatchDTO;
import com.ozo.easy.entity.SysDictData;
import com.ozo.easy.entity.SysDictType;
import com.ozo.easy.exception.ServiceExceptionEnum;
import com.ozo.easy.mapper.SysDictDataMapper;
import com.ozo.easy.mapper.SysDictTypeMapper;
import com.ozo.easy.pojo.dto.SysDictTypeQueryDTO;
import com.ozo.easy.pojo.dto.SysDictTypeSaveDTO;
import com.ozo.easy.pojo.vo.SysDictDataVO;
import com.ozo.easy.pojo.vo.SysDictTypeVO;
import com.ozo.easy.service.ISysDictTypeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 字典类型 服务实现类
 *
 * @author ozo
 * @version 1.0
 * @date 2025-01-21 10:37:26
 */
@RequiredArgsConstructor
@Service("dictService")
public class SysDictTypeServiceImpl extends ServiceImpl<SysDictTypeMapper, SysDictType> implements ISysDictTypeService {

    private final SysDictDataMapper sysDictDataMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(SysDictTypeSaveDTO saveDTO) {
        LambdaQueryWrapper<SysDictType> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysDictType::getDictCode, saveDTO.getDictCode());
        Long count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new ServiceException(ServiceExceptionEnum.DICT_CODE_EXISTS);
        }

        SysDictType sysDictType = BeanUtil.copyProperties(saveDTO, SysDictType.class);
        sysDictType.setEnableFlag(true);
        baseMapper.insert(sysDictType);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void remove(BaseBatchDTO<Long> batchDTO) {
        baseMapper.deleteBatchIds(batchDTO.getIdList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SysDictTypeSaveDTO saveDTO) {
        LambdaQueryWrapper<SysDictType> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysDictType::getDictCode, saveDTO.getDictCode())
                .ne(SysDictType::getId, saveDTO.getId());
        Long count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new ServiceException(ServiceExceptionEnum.DICT_CODE_EXISTS);
        }

        SysDictType sysDictType = BeanUtil.copyProperties(saveDTO, SysDictType.class);
        baseMapper.updateById(sysDictType);
    }

    @Override
    public List<SysDictTypeVO> list(SysDictTypeQueryDTO queryDTO) {
        QueryWrapper<SysDictType> queryWrapper = new QueryWrapper<>();
        // 排序
        queryWrapper.lambda().orderByDesc(SysDictType::getId);
        // 条件
        queryWrapper.lambda()
                .eq(Objects.nonNull(queryDTO.getEnableFlag()), SysDictType::getEnableFlag, queryDTO.getEnableFlag())
                .like(StrUtil.isNotBlank(queryDTO.getDictName()), SysDictType::getDictName, queryDTO.getDictName())
                .like(StrUtil.isNotBlank(queryDTO.getDictCode()), SysDictType::getDictCode, queryDTO.getDictCode());
        List<SysDictType> recordList = baseMapper.selectList(queryWrapper);

        return BeanUtil.copyToList(recordList, SysDictTypeVO.class);
    }

    @Override
    public void enable(Long id) {
        SysDictType sysDictType = baseMapper.selectById(id);
        if (Objects.isNull(sysDictType)) {
            throw new ServiceException(ServiceExceptionEnum.DATA_NOT_EXISTS);
        }
        sysDictType.setEnableFlag(!sysDictType.getEnableFlag());
        baseMapper.updateById(sysDictType);
    }

    @Override
    public SysDictTypeVO detail(Long id) {
        SysDictType sysDictType = baseMapper.selectById(id);
        if (Objects.isNull(sysDictType)) {
            throw new ServiceException(ServiceExceptionEnum.DATA_NOT_EXISTS);
        }
        return BeanUtil.copyProperties(sysDictType, SysDictTypeVO.class);
    }

    @Override
    public List<SysDictTypeVO> listType() {
        SysDictTypeQueryDTO queryDTO = new SysDictTypeQueryDTO();
        queryDTO.setEnableFlag(true);
        return this.list(queryDTO);
    }

    @Override
    public List<SysDictTypeVO> listTypeWithData() {
        List<SysDictTypeVO> typeVOList = this.listType();
        List<SysDictData> sysDictDataList = sysDictDataMapper.selectList(new LambdaQueryWrapper<>());
        List<SysDictDataVO> sysDictDataVOList = BeanUtil.copyToList(sysDictDataList, SysDictDataVO.class);
        Map<Long, List<SysDictDataVO>> map = sysDictDataVOList.stream().collect(Collectors.groupingBy(SysDictDataVO::getDictTypeId));
        for (SysDictTypeVO typeVO : typeVOList) {
            typeVO.setDataList(map.get(typeVO.getId()));
        }
        return typeVOList;
    }

    @Override
    public List<SysDictDataVO> listData(String dictCode) {
        SysDictType sysDictType = this.lambdaQuery().eq(SysDictType::getDictCode, dictCode).one();
        if (Objects.isNull(sysDictType)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<SysDictData> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysDictData::getDictTypeId, sysDictType.getId())
                .orderByAsc(SysDictData::getOrderNum);
        List<SysDictData> dataList = sysDictDataMapper.selectList(queryWrapper);
        return BeanUtil.copyToList(dataList, SysDictDataVO.class);
    }

}
